package com.lachesis.molecule.web.interceptor;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.lachesis.molecule.common.exception.RfForbiddenException;
import com.lachesis.molecule.specification.ApiMonitor;
import com.lachesis.molecule.web.spring.SpringContextContainer;

/** 
 * @ClassName: ApiMonitorInterceptor 
 * @Description: Api规范拦截器，当Api规范监测器监测失败时，除了获取接口文档描述以外的请求，全部返回异常状态 
 * @author shiwei.hu shiwei.hu@lachesis-mh.com
 * @date 2017年10月31日 下午7:39:09 
 *  
 */
class ApiMonitorInterceptor extends HandlerInterceptorAdapter{

    /** 
     * @Fields LOG : 日志器 
     */ 
    private static Logger LOG = Logger.getLogger(CommonInterceptor.class);

    /** 
     * @Fields APIMONITOR : Swagger API规范监测器 
     */ 
    private static ApiMonitor APIMONITOR = null;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (handler instanceof HandlerMethod) { 

            //      API规范扫描
            if(APIMONITOR == null) {

                Map<String, ApiMonitor> beanMap = SpringContextContainer.getBean(ApiMonitor.class);             
                if(beanMap.size() == 0) { 

                    LOG.error("在Spring配置文件中，没有声明Api规范扫描器");
                    throw new RfForbiddenException("在Spring配置文件中，没有声明Api规范扫描器");
                }
                else {

                    APIMONITOR = beanMap.entrySet().iterator().next().getValue();
                    if(beanMap.size() > 1) {
                        LOG.warn("在Spring配置文件中，声明了多个Api规范扫描器，系统将默认使用第一个");
                    }
                }

                APIMONITOR.startMonitor();
            }

            if(!APIMONITOR.isApiMeetsRegulation()) {

                LOG.error("在Controller中申明的接口，没有通过Api规范扫描器的检测");
                //              TODO: 添加接口规范扫描结果失败的页面跳转，而非扔异常
                throw new RfForbiddenException("在Controller中申明的接口，没有通过Api规范扫描器的检测");
            }

        }

        return true;
    }
}
